package com.harsom.camerademo.widgets

import android.content.Context
import android.util.AttributeSet
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import android.graphics.SurfaceTexture
import android.opengl.*
import com.harsom.camerademo.CameraInterface
import com.harsom.camerademo.MyApplication
import com.yuri.xlog.XLog


class CameraGLSurfaceView : GLSurfaceView, GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
    private var mContext: Context? = null
    private var mSurface: SurfaceTexture? = null
    private var mTextureID = -1
    private var mCameraMatrix: CameraMatrix? = null
    private var mPointsMatrix: PointsMatrix? = null

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        mContext = context
        setEGLContextClientVersion(3)
        setRenderer(this)
        renderMode = RENDERMODE_WHEN_DIRTY
    }

    override fun onResume() {
        super.onResume()
        XLog.d()
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        XLog.d()
        mTextureID = createTextureId()
        mSurface = SurfaceTexture(mTextureID)
        mSurface?.setOnFrameAvailableListener(this)

        mCameraMatrix = CameraMatrix(mTextureID)
        mPointsMatrix = PointsMatrix(false)
        mPointsMatrix?.isShowFaceRect = true

        XLog.d("surfaceView.width:$width,height:$height")
        CameraInterface.instance.openCamera()

        mCameraCallBack?.onSurfaceCreate()
    }


    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        XLog.d()
        //设置视窗大小及位置
        //前两个是起始位置，后面两个是宽
        //坐标系是Y轴朝上，左下角是0，X轴朝右，左下角是0.都是整数。
        GLES20.glViewport(0, 0, width, height)

        var ratio = width.toFloat() / height
        ratio = 1f // 这样OpenGL就可以按照屏幕框来画了，不是一个正方形了

        // this projection matrix is applied to object coordinates
        // in the onDrawFrame() method
        Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f)
        // Matrix.perspectiveM(mProjMatrix, 0, 0.382f, ratio, 3, 700);


        if (!CameraInterface.instance.isPreviewing()) {
            CameraInterface.instance.startPreview(mSurface!!)
        }
    }

    private val mMVPMatrix = FloatArray(16)
    private val mProjMatrix = FloatArray(16)
    private val mVMatrix = FloatArray(16)
    override fun onDrawFrame(gl: GL10?) {
        GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
        // 清除屏幕和深度缓存
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)

        //放在前面调用
//        mSurface?.updateTexImage()// 更新image，会调用onFrameAvailable方法

        val mtx = FloatArray(16)
        mSurface?.getTransformMatrix(mtx)
        mCameraMatrix?.draw(mtx)

//        // Set the camera position (View matrix)
        if (MyApplication.mScreenWidth > MyApplication.mScreenHeight) {
            //横屏
            Matrix.setLookAtM(mVMatrix, 0, 0f, 0f, -3f, 0f, 0f, 0f, -1f, 0f, 0f)
        } else {
            //竖屏
            Matrix.setLookAtM(mVMatrix, 0, 0f, 0f, -3f, 0f, 0f, 0f, 0f, 1f, 0f)
        }

//
//        // Calculate the projection and view transformation
        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0)
//
        mPointsMatrix?.draw(mMVPMatrix)

//        if (isDebug) {
//            runOnUiThread {
//                val endTime = System.currentTimeMillis() - actionTime
//                debugPrinttext.setText("printTime: $endTime")
//            }
//        }
        //放在最后调用
        mSurface?.updateTexImage()// 更新image，会调用onFrameAvailable方法
    }

    override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) {
        this.requestRender()
    }

    private fun createTextureId(): Int {
        val texture = IntArray(1)
//        XLog.xobject(texture)
        GLES20.glGenTextures(1, texture, 0)
//        XLog.xobject(texture)
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0])
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR.toFloat())
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR.toFloat())
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE)
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE)
        return texture[0]
    }

    fun getSurfaceTexture(): SurfaceTexture? {
        return mSurface
    }

    override fun onPause() {
        super.onPause()
        XLog.d()
        stopCamera()
    }

    fun switchCamera() {
        CameraInterface.instance.switchCamera()
        if (!CameraInterface.instance.isPreviewing()) {
            CameraInterface.instance.startPreview(mSurface!!)
        }
    }

    private fun stopCamera() {
        CameraInterface.instance.stopCamera()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        XLog.d()
        mSurface?.release()
        mSurface = null
    }


    private var mCameraCallBack: CameraCallBack? = null

    fun setCallBack(callBack: CameraCallBack) {
        mCameraCallBack = callBack
    }

    interface CameraCallBack {
        fun onSurfaceCreate()
    }

}